package FileTree;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import javax.swing.filechooser.FileSystemView;

/**
 *
 * @author popperik
 */
public class FileWrap {
    /*public */File file;
    ArrayList<FileWrap> children;
    FileSystemView fsv; // Used in toString()
    
    // Constructors
    
    protected FileWrap(File file) {
        this.file = file;
        children = null;
        fsv = FileSystemView.getFileSystemView();
    }
    
    // Nested classes
    
    protected static Comparator<FileWrap> filenameComparator = new Comparator<FileWrap>() {
        @Override
        public int compare(FileWrap o1, FileWrap o2) {
            return o1.toString().compareTo(o2.toString());
        }
    };
            
    // Static methods
    
    /**
     * Returns a list of the available roots in the current system
     */
    public static ArrayList<FileWrap> getAvailableRoots() {
        ArrayList<FileWrap> roots = new ArrayList<>();
        for(File root : File.listRoots()) {
            roots.add(new FileWrap(root));
        }
        Collections.sort(roots, filenameComparator);
        
        return roots;
    }
    
    // Member methods
    
    /**
     * Searches for the given child object and returns its index or -1 if not found.
     * @param child The child to be searched for
     * @return The index of the child or -1 if not found
     */
    public int findChild(FileWrap child) {
        return children.indexOf(child);
    }
    
    /**
     * Gets the children of the file object
     * @return A list of the children
     */
    public ArrayList<FileWrap> getChildren() {
        if(children == null) {
            loadChildren();
        }
        return children;
    }
    
    /**
     * Gets the child file object at the specified index
     * @param index The index of the to be returned file object
     * @return The file object at the specified index
     */
    public FileWrap getChildAt(int index) {
        if(children == null) {
            loadChildren();
        }
        return children.get(index);
    }
    
    /**
     * Counts the children of the file object
     * @return The number of children
     */
    public int getChildCount() {
        if(children == null) {
            loadChildren();
        }
        return children.size();
    }
    
    /**
     * Returns the size of a file object
     * @return The size of the file object
     */
    public long getLength() {
        return file.length();
    }
    
    /**
     * Checks whether the file object is a file or a folder
     * @return True, if it is a file, false if it is a folder
     */
    public boolean isFile() {
        return file.isFile();
    }
    
    /**
     * Loads the children of the file object, thus making them available for use.
     * Has to be called before trying to access this.children
     */
    protected void loadChildren() {
        children = new ArrayList<>();
        File[] rawChildren = file.listFiles();
        
        if(rawChildren != null) { // e.g. empty DVD drive
            for(File child : rawChildren) {
                children.add(new FileWrap(child));
            }
        }
        Collections.sort(children, filenameComparator);
    }
    
    @Override
    public String toString() {
        // getName returns empty string on root folders!
        if(fsv.isFileSystemRoot(file)) {
            return file.toString();
        }
        return file.getName();
    }
}
